00001 // Emacs Mode Line: -*- Mode:c++;-*- 00002 // ------------------------------------------------------------- 00003 /* 00004 * Copyright (c) 2013 Battelle Memorial Institute 00005 * Licensed under modified BSD License. A copy of this license can be found 00006 * in the LICENSE file in the top level directory of this distribution. 00007 */ 00008 // ------------------------------------------------------------- 00009 /** 00010 * @file linear_solver.hpp 00011 * @author William A. Perkins 00012 * @date 2015-08-18 13:37:16 d3g096 00013 * 00014 * @brief 00015 * 00016 * 00017 */ 00018 // ------------------------------------------------------------- 00019 00020 #ifndef _linear_solver_hpp_ 00021 #define _linear_solver_hpp_ 00022 00023 #include <boost/scoped_ptr.hpp> 00024 #include <gridpack/utilities/uncopyable.hpp> 00025 #include <gridpack/math/linear_solver_implementation.hpp> 00026 00027 namespace gridpack { 00028 namespace math { 00029 00030 // ------------------------------------------------------------- 00031 // class LinearSolver 00032 // ------------------------------------------------------------- 00033 /// A solver for system(s) of linear equations in parallel 00034 /** 00035 * A LinearSolver is used to solve a system of linear equations: 00036 * \f[ 00037 * \left[ \mathbf{A} \right] \mathbf{x} ~ = ~ \mathbf{b} 00038 * \f] 00039 * where \f$\left[ \mathbf{A} \right]\f$ is the coefficient matrix, 00040 * and \f$\mathbf{x}\f$ and \f$\mathbf{b}\f$ are vectors. 00041 * 00042 * A LinearSolver is instantiated using an existing coefficient 00043 * Matrix. It must be intantiated simutaneously on all processes 00044 * involved in the \ref parallel::Communicator "communicator" used by 00045 * the coefficent Matrix. It similarly must be destroyed 00046 * simultaneously on all processes. 00047 * 00048 * A particular system is solved using the solve() method, which 00049 * requires the \f$\mathbf{b}\f$ Vector and a Vector that serves as 00050 * the intial estimate of \f$\mathbf{x}\f$. Multiple systems can be 00051 * solved using the same coefficient matrix by repeatedly calling 00052 * solve() with different \f$\mathbf{b}\f$ and \f$\mathbf{x}\f$ 00053 * vectors. If the coefficient matrix changes in any way (even just 00054 * the coefficients) between system solutions, the setMatrix() method 00055 * must be called before solve(); 00056 * 00057 * This class encapuslates the linear system solver of the underlying 00058 * math library. The Pimpl idiom is used for \ref 00059 * LinearSolverImplementation "implementation", so user code is 00060 * completely independent of the underlying library. This class simply 00061 * provides an interface to a specific \ref LinearSolverImplementation 00062 * "implementation". 00063 * 00064 */ 00065 template <typename T, typename I = int> 00066 class LinearSolverT 00067 : public parallel::WrappedDistributed, 00068 public utility::WrappedConfigurable, 00069 private utility::Uncopyable, 00070 public BaseLinearSolverInterface<T, I> 00071 { 00072 public: 00073 00074 typedef typename BaseLinearSolverInterface<T, I>::MatrixType MatrixType; 00075 typedef typename BaseLinearSolverInterface<T, I>::VectorType VectorType; 00076 00077 /// Default constructor. 00078 /** 00079 * @e Collective 00080 * 00081 * This will create a LinearSolver instance on the same \ref 00082 * parallel::Communicator "communicator" used by the coefficient 00083 * Matrix @c A. All processes in the \ref parallel::Communicator 00084 * "communicator" must call this simultaneously. 00085 * 00086 * The Matrix @c A must exist for the life of this instance. 00087 * 00088 * @param A existing, filled coefficient matrix 00089 * 00090 * @return new LinearSolver instance 00091 */ 00092 LinearSolverT(MatrixType& A); 00093 00094 /// Destructor 00095 /** 00096 * @e Collective 00097 * 00098 * This destroys a LinearSolver. It must be called simutaneously by 00099 * all processes involved in calling the constructor. 00100 * 00101 */ 00102 ~LinearSolverT(void) 00103 {} 00104 00105 protected: 00106 00107 /// Where the work really happens 00108 /** 00109 * The Pimpl idiom is used for \ref LinearSolverImplementation 00110 * "implementation", so user code is completely independent of the 00111 * underlying library. This class simply provides an interface on a 00112 * specific \ref LinearSolverImplementation "implementation". 00113 */ 00114 boost::scoped_ptr< LinearSolverImplementation<T, I> > p_solver; 00115 00116 /// Get the solution tolerance (specialized) 00117 /** 00118 * 00119 * 00120 * 00121 * @return current solution tolerance 00122 */ 00123 double p_tolerance(void) const 00124 { 00125 return p_solver->tolerance(); 00126 } 00127 00128 /// Set the solver tolerance (specialized) 00129 /** 00130 * 00131 * 00132 * @param tol new solution tolerance 00133 */ 00134 void p_tolerance(const double& tol) 00135 { 00136 p_solver->tolerance(tol); 00137 } 00138 00139 /// Get the maximum iterations (specialized) 00140 /** 00141 * 00142 * 00143 * 00144 * @return current maximum number of solution iterations 00145 */ 00146 int p_maximumIterations(void) const 00147 { 00148 return p_solver->maximumIterations(); 00149 } 00150 00151 00152 /// Set the maximum solution iterations (specialized) 00153 /** 00154 * 00155 * 00156 * @param n new maximum number of iterations 00157 */ 00158 void p_maximumIterations(const int& n) 00159 { 00160 p_solver->maximumIterations(n); 00161 } 00162 00163 /// Solve w/ the specified RHS, put result in specified vector 00164 /** 00165 * @e Collective. 00166 * 00167 * Solve a linear system of equations. When called, Vector @c x 00168 * should contain the initial solution estimate. The final solution 00169 * is returned in @c x. 00170 * 00171 * The \ref parallel::Communicator "communicator" @c x and @c b must 00172 * be the same and match that of the coefficient Matrix used for 00173 * construction. The length of both @c x and @c b must the number of 00174 * columns in the coeffienct Matrix used for constructor or passed 00175 * the last call to setMatrix(). If these conditions are not met, 00176 * an \ref Exception "exception" is thrown. 00177 * 00178 * @param b Vector containing right hand side of linear system 00179 * @param x solution Vector 00180 */ 00181 void p_solve(const VectorType& b, VectorType& x) const 00182 { 00183 p_solver->solve(b, x); 00184 } 00185 00186 /// Solve again w/ the specified RHS, put result in specified vector (specialized) 00187 void p_resolve(const VectorType& b, VectorType& x) const 00188 { 00189 p_solver->resolve(b, x); 00190 } 00191 00192 /// Solve multiple systems w/ each column of the Matrix a single RHS 00193 /** 00194 * 00195 * 00196 * @param B RHS matrix -- each column is used as a RHS Vector 00197 * 00198 * @return @e dense solution Matrix -- each column is the solution for the corresponding column in @c B 00199 */ 00200 MatrixType *p_solve(const MatrixType& B) const 00201 { 00202 return p_solver->solve(B); 00203 } 00204 00205 00206 }; 00207 00208 typedef LinearSolverT<ComplexType> ComplexLinearSolver; 00209 typedef LinearSolverT<RealType> RealLinearSolver; 00210 00211 typedef ComplexLinearSolver LinearSolver; 00212 00213 } // namespace math 00214 } // namespace gridpack 00215 00216 #endif